home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr26 / netprog.zip / NETPROG.TAR / lib.s5 / udpopen.c < prev    next >
C/C++ Source or Header  |  1989-12-17  |  4KB  |  130 lines

  1. /*
  2.  * Establish a UDP socket and optionally call connect() to set up
  3.  * the server's address for future I/O.
  4.  */
  5.  
  6. #include    "netdefs.h"
  7.  
  8. #include    <netinet/in.h>
  9. #include    <arpa/inet.h>
  10.  
  11. #ifndef    INADDR_NONE
  12. #define    INADDR_NONE    0xffffffff    /* should be in <netinet/in.h> */
  13. #endif
  14.  
  15. /*
  16.  * The following globals are available to the caller, if desired.
  17.  */
  18.  
  19. struct sockaddr_in    udp_srv_addr;    /* server's Internet socket addr */
  20. struct sockaddr_in    udp_cli_addr;    /* client's Internet socket addr */
  21. struct servent        udp_serv_info;    /* from getservbyname() */
  22. struct hostent        udp_host_info;    /* from gethostbyname() */
  23.  
  24. int            /* return socket descriptor if OK, else -1 on error */
  25. udp_open(host, service, port, dontconn)
  26. char    *host;        /* name of other system to communicate with */
  27. char    *service;    /* name of service being requested */
  28.             /* can be NULL, iff port > 0 */
  29. int    port;        /* if == 0, nothing special - use port# of service */
  30.             /* if < 0, bind a local reserved port */
  31.             /* if > 0, it's the port# of server (host-byte-order) */
  32. int    dontconn;    /* if == 0, call connect(), else don't */
  33. {
  34.     int        fd;
  35.     unsigned long    inaddr;
  36.     char        *host_err_str();
  37.     struct servent    *sp;
  38.     struct hostent    *hp;
  39.  
  40.     /*
  41.      * Initialize the server's Internet address structure.
  42.      * We'll store the actual 4-byte Internet address and the
  43.      * 2-byte port# below.
  44.      */
  45.  
  46.     bzero((char *) &udp_srv_addr, sizeof(udp_srv_addr));
  47.     udp_srv_addr.sin_family = AF_INET;
  48.  
  49.     if (service != NULL) {
  50.         if ( (sp = getservbyname(service, "udp")) == NULL) {
  51.             err_ret("udp_open: unknown service: %s/udp", service);
  52.             return(-1);
  53.         }
  54.         udp_serv_info = *sp;            /* structure copy */
  55.         if (port > 0)
  56.             udp_srv_addr.sin_port = htons(port);
  57.                             /* caller's value */
  58.         else
  59.             udp_srv_addr.sin_port = sp->s_port;
  60.                             /* service's value */
  61.     } else {
  62.         if (port <= 0) {
  63.             err_ret("udp_open: must specify either service or port");
  64.             return(-1);
  65.         }
  66.         udp_srv_addr.sin_port = htons(port);
  67.     }
  68.  
  69.     /*
  70.      * First try to convert the host name as a dotted-decimal number.
  71.      * Only if that fails do we call gethostbyname().
  72.      */
  73.  
  74.     if ( (inaddr = inet_addr(host)) != INADDR_NONE) {
  75.                         /* it's dotted-decimal */
  76.         bcopy((char *) &inaddr, (char *) &udp_srv_addr.sin_addr,
  77.             sizeof(inaddr));
  78.         udp_host_info.h_name = NULL;
  79.  
  80.     } else {
  81.         if ( (hp = gethostbyname(host)) == NULL) {
  82.             err_ret("udp_open: host name error: %s %s",
  83.                         host, host_err_str());
  84.             return(-1);
  85.         }
  86.         udp_host_info = *hp;    /* found it by name, structure copy */
  87.         bcopy(hp->h_addr, (char *) &udp_srv_addr.sin_addr,
  88.             hp->h_length);
  89.     }
  90.  
  91.     if (port < 0)
  92.         err_quit("udp_open: reserved ports not implemeneted yet");
  93.  
  94.     if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  95.         err_ret("udp_open: can't create UDP socket");
  96.         return(-1);
  97.     }
  98.  
  99.     /*
  100.      * Bind any local address for us.
  101.      */
  102.  
  103.     bzero((char *) &udp_cli_addr, sizeof(udp_cli_addr));
  104.     udp_cli_addr.sin_family      = AF_INET;
  105.     udp_cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  106.     udp_cli_addr.sin_port        = htons(0);
  107.     if (bind(fd, (struct sockaddr *) &udp_cli_addr,
  108.                         sizeof(udp_cli_addr)) < 0) {
  109.         err_ret("udp_open: bind error");
  110.         close(fd);
  111.         return(-1);
  112.     }
  113.  
  114.     /*
  115.      * Call connect, if desired.  This is used by most caller's,
  116.      * as the peer shouldn't change.  (TFTP is an exception.)
  117.      * By calling connect, the caller can call send() and recv().
  118.      */
  119.  
  120.     if (dontconn == 0) {
  121.         if (connect(fd, (struct sockaddr *) &udp_srv_addr,
  122.                         sizeof(udp_srv_addr)) < 0) {
  123.             err_ret("udp_open: connect error");
  124.             return(-1);
  125.         }
  126.     }
  127.  
  128.     return(fd);
  129. }
  130.